# 导入的包
from lib import common
import hashlib
from conf import settings
import os
import sys
import json
import pickle

# 全局字典
dic = {"name": None, "identity": None}


# 学生类
class Student:
    # 功能列表
    lst = [("查看所有课程", "show_courses"), ("选择课程", "select_course"), ("查看所选课程", "show_selected_course"), ("退出", "exit")]

    # __init__函数
    def __init__(self, name):
        # 学生姓名
        self.name = name

    # 查看可选课程
    def show_courses(self):
        """
        查看可选课程
        :return:
        """
        print(f"{'欢迎来到查询课程界面'.center(30, '-')}")
        # 计数
        count = 1
        # 打开课程文件
        with open(settings.COURSE_PATH, mode='rb') as f5:
            while 1:
                try:
                    # 把课程文件里面的所有文件都打印出来
                    if os.path.getsize(settings.COURSE_PATH) == 0:
                        print("没有课程，请创建课程！")
                        break
                    else:
                        # 把课程对象取出来
                        obj = pickle.load(f5)
                        # 打印课程序号和课程展示
                        print(f"{count} {obj.course_show()}")
                        count += 1
                except Exception:
                    break

    # 选择课程
    def select_course(self):
        """
        选择课程
        :return:
        """
        print(f"{'欢迎来到选择课程界面'.center(30, '-')}")
        count = 1
        obj_count = 0
        lst3 = []
        # 打开课程文件
        with open(settings.COURSE_PATH, mode='rb') as f5:
            # 得到课程数量
            while 1:
                try:
                    obj = pickle.load(f5)
                    obj_count += 1
                except Exception:
                    break
        # 打开课程文件
        with open(settings.COURSE_PATH, mode='rb') as f6:
            while True:
                # 输入课程序号
                num = input("请输入你想报的课程序号：").replace(" ","")
                # 打开学生文件
                with open(settings.STUDENT_PATH, "r", encoding="utf-8")as f7:
                    for i in f7:
                        # 把学生的所有选择的课程都存储起来
                        if self.name == i.split("|")[0]:
                            lst3.append(i.split("|")[1].strip())
                # 判断序号
                if num.isdecimal() and 1 <= int(num) <= obj_count:
                    while True:
                        try:
                            # 取出课程对象
                            obj1 = pickle.load(f6)
                            # 计数取课程名
                            if int(num) == count:
                                print(f"你选择的课程是：{obj1.name}")
                                # 判断学生是否重复选课
                                if obj1.name not in lst3:
                                    with open(settings.STUDENT_PATH, "a", encoding="utf-8")as f8:
                                        f8.write(f"{self.name}|{obj1.name}\n")
                                else:
                                    print("该课程已经报名了！")
                                break
                            count += 1
                        except Exception:
                            break
                    break
                else:
                    print("输入错误！")

    # 查看所选课程
    def show_selected_course(self):
        """
        查看所选课程
        :return:
        """
        # 判断学生是否有选课
        if os.path.getsize(settings.STUDENT_PATH) == 0:
            print("没有学生选课！")
        else:
            # 打开学生文件
            with open(settings.STUDENT_PATH, "r", encoding="utf-8")as f:
                for i in f:
                    # 取出所选课程
                    if self.name == i.split("|")[0]:
                        print(i.split("|")[1].strip())

    # 退出
    def exit(self):
        """
        退出
        :return:
        """
        pass


# 管理员类
class Manager:
    # 功能列表
    lst = [
        ("创建课程", "create_course"),
        ("创建学生", "create_student"),
        ("查看可选课程", "show_courses"),
        ("查看所有学生", "show_students"),
        ("查看所有学生选课情况", "show_students_courses"),
        ("退出", "exit")
    ]

    # __init__函数
    def __init__(self, name):
        self.name = name

    # 创建课程
    def create_course(self):
        """
        创建课程
        :return:
        """
        print(f"{'欢迎来到创建课程界面'.center(30, '-')}")
        # 退出循环条件
        break_a = 0
        while 1:
            # 输入课程名
            course_name = input("请输入你想添加的课程名：").replace(" ", "")
            # 判断课程是否存在，存在返回回来重新输入
            # 打开课程文件
            with open(settings.COURSE_PATH, mode='rb') as f3:
                while 1:
                    try:
                        # 取出课程对象
                        obj = pickle.load(f3)
                        # 判断课程是否存在
                        if course_name == obj.name:
                            print("该课程已经存在！，请重新输入！")
                            break_a = 1
                            break
                    except Exception:
                        break
            # 课程存在返回循环
            if break_a == 1:
                continue
            course_price = input("请输入你想添加的价格：")
            course_period = input("请输入你想添加的周期：")
            # 实例化课程对象
            obj = Course(course_name, course_price, course_period)
            # 打开课程文件，进行添加
            with open(settings.COURSE_PATH, "ab")as f4:
                pickle.dump(obj, f4)
                print("创建成功！")
                # 把记录写入用户日志文件
                common.all_log(f"添加了{course_name}课程！")
                break

    # 创建学生
    def create_student(self):
        """
        创建学生
        :return:
        """
        print(f"{'欢迎来到创建学生界面'.center(30, '-')}")
        # 循环创建学生账号
        while True:
            add_name = input("请输入你想添加的学生姓名：")
            add_pwd = input("请输入你想添加的学生密码：")
            # 加密准备
            md5 = hashlib.md5()
            md5.update(add_pwd.encode("utf-8"))
            # 打开Userinfo文件
            with open(settings.LOGIN_PATH, "r", encoding="utf-8")as f6:
                # 把名字存入lst2列表中
                lst2 = [i.split("|")[0] for i in f6]
            # 判断学生是否已经存在
            if add_name not in lst2:
                # 打开Userinfo文件，添加学生账号
                with open(settings.LOGIN_PATH, "a", encoding="utf-8")as f7:
                    f7.write(f"\n{add_name}|{md5.hexdigest()}|Student")
                    print("创建成功！")
                    common.all_log(f"添加了{add_name}学生！")
                    break
            else:
                print("该学生已经存在！")

    # 查看可选课程
    def show_courses(self):
        """
        查看可选课程
        :return:
        """
        print(f"{'欢迎来到查询课程界面'.center(30, '-')}")
        # 打开课程文件
        with open(settings.COURSE_PATH, mode='rb') as f5:
            while 1:
                try:
                    # 判断文件中是否有课程
                    if os.path.getsize(settings.COURSE_PATH) == 0:
                        print("没有课程，请创建课程！")
                        break
                    else:
                        # 打印所有课程
                        obj = pickle.load(f5)
                        print(obj.course_show())
                except Exception:
                    break

    # 查看所有学生
    def show_students(self):
        """
        查看所有学生
        :return:
        """
        print(f"{'欢迎来到查询学生界面'.center(30, '-')}")
        # 判断文件中是否有学生
        if os.path.getsize(settings.LOGIN_PATH) == 0:
            print("没有学生，请创建学生！")
        else:
            # 打开Userinfo文件
            with open(settings.LOGIN_PATH, "r", encoding="utf-8")as f8:
                for i in f8:
                    # 判断是管理员还是学生
                    if i.split("|")[2].strip() == "Student":
                        print(i.split("|")[0])

    # 查看所有学生选课情况
    def show_students_courses(self):
        """
        查看所有学生选课情况
        :return:
        """
        print(f"{'欢迎来到查询学生选课情况界面'.center(30, '-')}")
        dic_show = {}
        # 判断文件中是否有学生选课
        if os.path.getsize(settings.STUDENT_PATH) == 0:
            print("没有学生选课！")
        else:
            # 打开学生文件，打印所有学生选课记录
            with open(settings.STUDENT_PATH, "r", encoding="utf-8")as f:
                # 循环把学生选课记录加入字典中
                for i in f:
                    if i.split("|")[0] in dic_show:
                        dic_show[i.split("|")[0]].append(i.split("|")[1].strip())
                    else:
                        dic_show[i.split("|")[0]] = [i.split("|")[1].strip()]
                # 打印所有学生选课记录
                for m, n in dic_show.items():
                    print(f"{m}选择了{n}课程")

    # 退出
    def exit(self):
        """
        退出
        :return:
        """


# 课程类
class Course:
    # 创建对象属性 name、price、period
    def __init__(self, name, price, period):
        self.name = name
        self.price = price
        self.period = period

    # 打印课程事例
    def course_show(self):
        return f"课程名：{self.name},价格：{self.price},周期：{self.period}个月"


# 登录
def login():
    """
    登录界面
    :return:
    """
    # 登录次数
    for i in range(3, 0, -1):
        print(f"还剩余{i}次登录机会！")
        # 用户登录姓名
        name = common.pass_name()
        # 用户登录密码
        word = common.pass_word()
        # 用户密码解密准备
        md5 = hashlib.md5()
        md5.update(word.encode("utf-8"))
        # 判断用户是否存在
        with open(settings.LOGIN_PATH, "r", encoding="utf-8")as f1:
            lst1 = [i.split("|")[0] for i in f1]
        if name in lst1:
            with open(settings.LOGIN_PATH, "r", encoding="utf-8")as f2:
                for j in f2:
                    # 判断密码是否相同
                    if j.split("|")[1] == md5.hexdigest():
                        # 密码相等
                        # 把记录写入用户日志
                        dic["name"] = name
                        dic["identity"] = j.split("|")[2]
                        return "登录成功！"
                else:
                    # 密码不相等
                    print("密码错误！")
                    # 让三次机会没有退出程序
                    if i == 1:
                        global enter_p
                        enter_p = 1
                        print("三次机会已过，自动退出程序！")
        else:
            # 用户不存在
            print("该用户没有注册！")


# 主文件
def main():
    """
    程序入口
    :return:
    """
    print(f"{'欢迎来到学生选课系统'.center(100, '-')}")
    # 进行登录
    print(login())
    # 登录成功判断本文件是否xxx类
    if hasattr(sys.modules[__name__], dic["identity"].strip()):
        # 实例化xxx类对象
        obj = getattr(sys.modules[__name__], dic["identity"].strip())(dic["name"])
        # 循环打印功能列表
        for num, content in enumerate(obj.lst):
            print(f'{num+1} {content[0]}')
            # 循环运行类中的功能
        while 1:
            choose = input("请输入你想选择的功能序号：").replace(" ", "")
            # 应用功能
            if choose.isdecimal() and 1 <= int(choose) <= len(obj.lst)-1:
                getattr(obj, obj.lst[int(choose)-1][1])()
            # 退出功能
            elif choose == f"{len(obj.lst)}":
                print("已退出")
                break
            else:
                print("输入错误！")
